# -*- coding:utf-8 -*- 
import urllib
import urllib.request
from urllib import request
import chardet
from lxml import etree
from urlclass import Urlhecheng
import os
import codecs
import jieba
import jieba.posseg
from collections import Counter



class Tongji():
    """统计数据,传入列表进行词频统计 
    词频统计：Tongji(实参).cipin()
    """
    def __init__(self,name):
        self.name = name
        self.word_dict = {}
        self.word_list = []
        self.cipin()

    def cipin(self):
        """
        将列表的元素进行词频统计，并以字典形式返回。
        """
        for item in self.name:
            if item not in self.word_dict:
                self.word_dict[item] = 1
            else:
                self.word_dict[item] += 1
        return self.word_dict

class Htmlchuli():
    """
    处理html数据需要传入的实参及函数方法作用:
    Htmlchuli(url,关键词相对路径默认：'./data/key/keys.txt',ci=关键词出现n次以上,n=分词的关键词至少出现n次,timeout=连接超时设置)
    html_open()           >>>自动获取当前url网页的编码，返回网页相关信息；
    html_etat()           >>>通过xpath提取网页值及新url等；
    html_if_key()         >>>将提取到的数据进行关键词对比及返回数据；
    html_fen_parti(次数)   >>>默认0次填入筛选出出现n次以上分词的词频
    html_fen_parti(次数)   >>>将网页值进行分词并筛选n次以上的词返回元组。
    """

    def __init__(self,url,route='./data/key/keys.txt',ci=0,n=0,timeout=10):
        self.url = url
        self.route = route
        self.ci = ci
        self.n = n
        self.timeout = timeout
        self.tichu = []
        self.headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"}
        self.html_open()
        self.html_etat()
        self.html_fen_parti()
        self.html_if_key()

    def html_open(self):
        """
        此函数主要为打开网页并判断网页信息的方法；
        传入url将以当前url的html编码方式打开并返回html的字符串数据；
        因为有时候获取到的网页编码并非正确，所以使用异常处理try依次为utf-8、gbk；
        获取并已正确编码打开后将网页格式化为xpath可用对象。
        """
        rks = request.Request(self.url,headers=self.headers)
        html_kai = urllib.request.urlopen(rks,timeout=self.timeout).read()
        html_info = chardet.detect(html_kai)
        try:
            self.doct_open = html_kai.decode(html_info['encoding'])
        except UnicodeDecodeError:
            try:
                self.doct_open = html_kai.decode('utf-8')
            except UnicodeDecodeError:
                self.doct_open = html_kai.decode('gbk')

        self.html_struc = etree.HTML(self.doct_open)

    def html_etat(self):
        """
        html_etat()方法主要用于处理当前网页需要获取的各种值和新的链接
        """
        self.url_list = [] # 储存网页中获取到并拼接好的url
        self.txt_fs = '' # 将网页中所有内容组合成为一个字符串方便判断关键词是否存在
        self.biao_txt = '' # 储存获取到的网页标题，以便下个方法函数使用
        struc = self.html_struc # 将html对象后的值赋值到struc，以便调用
        name_title = struc.xpath('/html/head/title/text()')  # 获取当前网页的SEO title标题
        for bt_txt in name_title:  # 将xpath提取出来的列表元素遍历成为字符串
            self.txt_fs += bt_txt # 标题字符串赋值到txt_fs
            self.biao_txt = bt_txt # 赋值到biao_txt中，以便下个函数方法调用 
        text_p = struc.xpath('string(.)') # 通过xpath的string(.)函数获取当前网页的所有值
        for txt_n in text_p: # 遍历这些所有值为字符串
            self.txt_fs += txt_n.strip() # 网页所有值赋值到txt_fs，并用strip()函数去除首尾空格
        name_url = struc.xpath('//a/@href') # 获取网页中的所有a标签下的链接
        if name_url: # 判断前面是否获取到a标签下的链接
            for x_url in name_url: # 把链接遍历出来
                list_url = Urlhecheng(self.url,x_url).pingjie() # 将遍历出来的链接交给url合成类处理拼接url
                self.url_list.append(list_url) # 将拼接后的url添加到url_list列表当中

        return self.url_list
        
    def html_fen_parti(self):
        """
        html_fen_parti(次数) 默认0次填入筛选出出现n次以上分词的词频
        采用分词将网页的所有值分词并计算词频
        """
        fenci = [(x.word,x.flag) for x in jieba.posseg.cut(self.txt_fs)]
        jiping = Counter(fenci).most_common()
        for qu in jiping:
            if qu[1] > self.n:  # 判断出现的次数
                if 'x' in qu[0][1]:  # 判断是否是x词性（标点符号）
                    continue
                elif 'm' in qu[0][1]:
                    continue
                else:
                    if len(qu[0][0]) >= 2:
                        self.tichu.append(qu)  # 如果都排除以上词性将把该元组加入的tichu的列表里面
        return self.tichu

    def html_if_key(self):
        """将提取到的数据进行关键词对比及返回数据"""
        pingci = [] # 用于播报当前网页关键词出现次数
        ci_dict = {} # 以字典形式储存关键词在该网页出现的次数、url、标题
        route = os.path.abspath(self.route) # 写明关键词的相对路径和文件名；默认：'./data/key/keys.txt'
        with codecs.open(route,'r','utf-8') as open_txt:  # 以只读方式的utf-8编码打开
            for txt in open_txt: # 遍历所有需要获取的关键词
                iftxt = self.txt_fs.count(txt.strip()) # 将txt_fs字符串用count()函数搜索遍历出来的关键词出现了多少次，这里需要注意去除首尾空格，不然会连同空格也当做搜索字符
                if iftxt > self.ci: # 默认如果大于0次以上
                    gs = txt.strip() # 将遍历出来的关键词赋值到gs
                    dqtxt = txt.strip() + '  ======>>>>>  ' + str(iftxt) + '次'  # 打印执行后的结果并赋值
                    pingci.append(dqtxt) # 将字符串添加到pingci的列表当中，方便播报
                    ci_dict[gs] = [{'次数':iftxt,'url':self.url,'标题':self.biao_txt,'词频':self.tichu}] # 将关键词以字典形式储存，关键词下包含一个列表字典，以便后期调用遍历筛选结果
        if ci_dict:
            pass
        else:
            ci_dict = [{'标题':self.biao_txt,'url':self.url,'词频':self.tichu}]  # 判断如果没有检测到关键词则返回当前网页的词频信息

        return pingci,ci_dict
